home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / gfxobj.c < prev    next >
C/C++ Source or Header  |  1999-09-03  |  11KB  |  398 lines

  1. /*
  2.     gfx object manager
  3.  
  4.     Games currently using the Sprite Manager:
  5.         Namco System1
  6.  
  7.     Graphic Object Manager controls all Graphic object and the priority.
  8.  
  9.     The thing to draw in tile of gfx element by an arbitrary size can be done.
  10.     That is,  it is useful for the sprite system which shares a different size.
  11.  
  12.     The drawing routine can be replaced with callbacking user routine.
  13.     The control of priority becomes easy if tilemap draws by using this function.
  14.     If gfx like special drawing routine is made,complexity overlapping sprite can be include.
  15.  
  16.     Currently supported features include:
  17.     - The position and the size can be arbitrarily specified from gfx tile.
  18.       ( It is achieved by using clipping.)
  19.     -  priority ordering.
  20.     - resource tracking (gfxobj_init and gfxobj_close must be called by mame.c)
  21.     - offscreen object skipping
  22.  
  23.     Schedule for the future
  24.     - zoomming gfx with selectable tile position and size
  25.     - palette usage tracking
  26.     - uniting with Sprite Manager
  27.     - priority link system in object list.
  28.  
  29.     Hint:
  30.  
  31.     -The position and the size select :
  32.  
  33.     This is similar to SPRITE_TYPE_UNPACK of Sprite Manager.
  34.     (see also comments in sprite.c.)
  35.  
  36.     objects->top
  37.     objects->left    -> The display beginning position in gfx tile is specified.
  38.     objects->width
  39.     objects->height  -> The display size is specified.
  40.  
  41.     Gfx object manager adjust the draw position from the value of top and left.
  42.     And,the clipping position is adjusted according to the size.
  43.  
  44.     -The palette resource tracking :
  45.  
  46.     sprite manager it not supported yet.
  47.     User should control palette resource for yourself.
  48.     If you use sort mode,the object not seen has exclusion from the object link.
  49.     Therefore,  examining objectlink will decrease the overhead.
  50.  
  51.     example:
  52.  
  53.     gfxobj_update();
  54.     if(object=objectlist->first_object ; object != 0 ; object=object->next)
  55.     {
  56.         color = object->color;
  57.         mark_palette_used_flag(color);
  58.     }
  59.  
  60.     -Priority order
  61.  
  62.     Gfx object manager can sort the object by priority.
  63.     The condition of sorting is decided by the flag.
  64.  
  65.     gfxobject_list->sort_type;
  66.  
  67.     GFXOBJ_DONT_SORT:
  68.  
  69.     Sorting is not done.
  70.     The user should be build object link list.
  71.     excluded objects from link are not updated.
  72.  
  73.     gfxobject_list->first_object; -> first object point (lower object)
  74.     gfxobject->next               -> next object point ,0 = end of link(higher)
  75.  
  76.     GFXOBJ_DOT_SORT:
  77.  
  78.     Sorting is done.
  79.  
  80.     The condition by object->priority is given to priority most.
  81.         object->priority = p    -> p=0 : lower , p=object_list->max_priority-1 : higher
  82.     If 'GFXOBJ_SORT_PRIORITY_BACK' is specified,  order is reversed.
  83.  
  84.     Next,  the array of object is given to priority.
  85.         object_list->objects[x] -> x=0 : lower , x=object_list->nums-1 = higher
  86.     If 'GFXOBJ_SORT_OBJECT_BACK' is specified,  order is reversed.
  87.  
  88.     -The handling of tilemap :
  89.  
  90.     Tilemap can be treated by the callback function as one object.
  91.  
  92.     If the user function is registered in object->special_handler,
  93.     the user function is called instead of drawgfx.
  94.  
  95.     Call tilemap_draw() in your callback handler.
  96.     If object->code is numbered with two or more tilemap,it might be good.
  97.  
  98.     If you adjust objects->gfx to 0,Useless processing to tilemap is omitted.
  99.     clipping,drawposition,visible,dirty_flag are not updated.
  100.  
  101.     If one tilemap is displayed with background and foreground
  102.     Use two objects behind in front of sprite.
  103.  
  104.     Example:
  105.  
  106.     object resource:
  107.  
  108.     objects[0]   ==  tilemap1 , higher background
  109.     objects[1]   ==  tilemap2 , lower  background
  110.     objects[3]   ==  lower sprite
  111.     objects[4]   ==  middle sprite
  112.     objects[5]   ==  higher sprite
  113.     objects[2]   ==  tilemap2 , foreground
  114.  
  115.     objects[0].code  = 1;  number of tilemap_2
  116.     objects[0].color = 0;  background mark
  117.     objects[1].code  = 0;  number of tilemap_1
  118.     objects[1].color = 0;  background mark
  119.     objects[5].code  = 0;  number of tilemap_1
  120.     objects[5].color = 1;  foreground mark
  121.  
  122.     objects[0,1,5].special_handler = object_draw_tile;
  123.     objects[0,1,5].gfx = 0;
  124.  
  125.     callback handler:
  126.  
  127.     void object_draw_tile(struct osd_bitmap *bitmap,struct gfx_object *object)
  128.     {
  129.         tilemap_draw( bitmap , tilemap[object->code] , object->color );
  130.     }
  131.  
  132. */
  133.  
  134. #include "driver.h"
  135. /* #include "gfxobj.h" */
  136.  
  137. static struct gfx_object_list *first_object_list;
  138.  
  139. void gfxobj_init(void)
  140. {
  141.     first_object_list = 0;
  142. }
  143.  
  144. void gfxobj_close(void)
  145. {
  146.     struct gfx_object_list *object_list,*object_next;
  147.     for(object_list = first_object_list ; object_list != 0 ; object_list=object_next)
  148.     {
  149.         free(object_list->objects);
  150.         object_next = object_list->next;
  151.         free(object_list);
  152.     }
  153. }
  154.  
  155. #define MAX_PRIORITY 16
  156. struct gfx_object_list *gfxobj_create(int nums,int max_priority,const struct gfx_object *def_object)
  157. {
  158.     struct gfx_object_list *object_list;
  159.     int i;
  160.  
  161.     /* priority limit check */
  162.     if(max_priority >= MAX_PRIORITY)
  163.         return 0;
  164.  
  165.     /* allocate object liset */
  166.     if( (object_list = malloc(sizeof(struct gfx_object_list))) == 0 )
  167.         return 0;
  168.     memset(object_list,0,sizeof(struct gfx_object_list));
  169.  
  170.     /* allocate objects */
  171.     if( (object_list->objects = malloc(nums*sizeof(struct gfx_object))) == 0)
  172.     {
  173.         free(object_list);
  174.         return 0;
  175.     }
  176.     if(def_object == 0)
  177.     {    /* clear all objects */
  178.         memset(object_list->objects,0,nums*sizeof(struct gfx_object));
  179.     }
  180.     else
  181.     {    /* preset with default objects */
  182.         for(i=0;i<nums;i++)
  183.             memcpy(&object_list->objects[i],def_object,sizeof(struct gfx_object));
  184.     }
  185.     /* setup objects */
  186.     for(i=0;i<nums;i++)
  187.     {
  188.         /*    dirty flag */
  189.         object_list->objects[i].dirty_flag = GFXOBJ_DIRTY_ALL;
  190.         /* link map */
  191.         object_list->objects[i].next = &object_list->objects[i+1];
  192.     }
  193.     /* setup object_list */
  194.     object_list->max_priority = max_priority;
  195.     object_list->nums = nums;
  196.     object_list->first_object = object_list->objects; /* top of link */
  197.     object_list->objects[nums-1].next = 0; /* bottom of link */
  198.     object_list->sort_type = GFXOBJ_SORT_DEFAULT;
  199.     /* resource tracking */
  200.     object_list->next = first_object_list;
  201.     first_object_list = object_list;
  202.  
  203.     return object_list;
  204. }
  205.  
  206. /* set pixel dirty flag */
  207. void gfxobj_mark_all_pixels_dirty(struct gfx_object_list *object_list)
  208. {
  209.     /* don't care , gfx object manager don't keep color remapped bitmap */
  210. }
  211.  
  212. /* update object */
  213. static void object_update(struct gfx_object *object)
  214. {
  215.     int min_x,min_y,max_x,max_y;
  216.  
  217.     /* clear dirty flag */
  218.     object->dirty_flag = 0;
  219.  
  220.     /* if gfx == 0 ,then bypass (for special_handler ) */
  221.     if(object->gfx == 0)
  222.         return;
  223.  
  224.     /* check visible area */
  225.     min_x = Machine->drv->visible_area.min_x;
  226.     max_x = Machine->drv->visible_area.max_x;
  227.     min_y = Machine->drv->visible_area.min_y;
  228.     max_y = Machine->drv->visible_area.max_y;
  229.     if(
  230.         (object->width==0)  ||
  231.         (object->height==0) ||
  232.         (object->sx > max_x) ||
  233.         (object->sy > max_y) ||
  234.         (object->sx+object->width  <= min_x) ||
  235.         (object->sy+object->height <= min_y) )
  236.     {    /* outside of visible area */
  237.         object->visible = 0;
  238.         return;
  239.     }
  240.     object->visible = 1;
  241.     /* set draw position with adjust source offset */
  242.     object->draw_x = object->sx -
  243.         (    object->flipx ?
  244.             (object->gfx->width - (object->left + object->width)) : /* flip */
  245.             (object->left) /* non flip */
  246.         );
  247.  
  248.     object->draw_y = object->sy -
  249.         (    object->flipy ?
  250.             (object->gfx->height - (object->top + object->height)) : /* flip */
  251.             (object->top) /* non flip */
  252.         );
  253.     /* set clipping point to object draw area */
  254.     object->clip.min_x = object->sx;
  255.     object->clip.max_x = object->sx + object->width -1;
  256.     object->clip.min_y = object->sy;
  257.     object->clip.max_y = object->sy + object->height -1;
  258.     /* adjust clipping point with visible area */
  259.     if (object->clip.min_x < min_x) object->clip.min_x = min_x;
  260.     if (object->clip.max_x > max_x) object->clip.max_x = max_x;
  261.     if (object->clip.min_y < min_y) object->clip.min_y = min_y;
  262.     if (object->clip.max_y > max_y) object->clip.max_y = max_y;
  263. }
  264.  
  265. /* update one of object list */
  266. static void gfxobj_update_one(struct gfx_object_list *object_list)
  267. {
  268.     struct gfx_object *object;
  269.     struct gfx_object *start_object,*last_object;
  270.     int dx,start_priority,end_priority;
  271.     int priorities = object_list->max_priority;
  272.     int priority;
  273.  
  274.     if(object_list->sort_type&GFXOBJ_DO_SORT)
  275.     {
  276.         struct gfx_object *top_object[MAX_PRIORITY],*end_object[MAX_PRIORITY];
  277.         /* object sort direction */
  278.         if(object_list->sort_type&GFXOBJ_SORT_OBJECT_BACK)
  279.         {
  280.             start_object   = object_list->objects + object_list->nums-1;
  281.             last_object    = object_list->objects-1;
  282.             dx = -1;
  283.         }
  284.         else
  285.         {
  286.             start_object = object_list->objects;
  287.             last_object  = object_list->objects + object_list->nums;
  288.             dx = 1;
  289.         }
  290.         /* reset each priority point */
  291.         for( priority = 0; priority < priorities; priority++ )
  292.             end_object[priority] = 0;
  293.         /* update and sort */
  294.         for(object=start_object ; object != last_object ; object+=dx)
  295.         {
  296.             /* update all objects */
  297.             if(object->dirty_flag)
  298.                 object_update(object);
  299.             /* store link */
  300.             if(object->visible)
  301.             {
  302.                 priority = object->priority;
  303.                 if(end_object[priority])
  304.                     end_object[priority]->next = object;
  305.                 else
  306.                     top_object[priority] = object;
  307.                 end_object[priority] = object;
  308.             }
  309.         }
  310.  
  311.         /* priority sort direction */
  312.         if(object_list->sort_type&GFXOBJ_SORT_PRIORITY_BACK)
  313.         {
  314.             start_priority = priorities-1;
  315.             end_priority   = -1;
  316.             dx = -1;
  317.         }
  318.         else
  319.         {
  320.             start_priority = 0;
  321.             end_priority   = priorities;
  322.             dx = 1;
  323.         }
  324.         /* link between priority */
  325.         last_object = 0;
  326.         for( priority = start_priority; priority != end_priority; priority+=dx )
  327.         {
  328.             if(end_object[priority])
  329.             {
  330.                 if(last_object)
  331.                     last_object->next = top_object[priority];
  332.                 else
  333.                     object_list->first_object = top_object[priority];
  334.                 last_object = end_object[priority];
  335.             }
  336.         }
  337.         if(last_object == 0 )
  338.             object_list->first_object = 0;
  339.         else
  340.             last_object->next = 0;
  341.     }
  342.     else
  343.     {    /* non sort , update only linked object */
  344.         for(object=object_list->first_object ; object !=0 ; object=object->next)
  345.         {
  346.             /* update all objects */
  347.             if(object->dirty_flag)
  348.                 object_update(object);
  349.         }
  350.     }
  351.     /* palette resource */
  352.     if(object->palette_flag)
  353.     {
  354.         /* !!!!! do not supported yet !!!!! */
  355.     }
  356. }
  357.  
  358. void gfxobj_update(void)
  359. {
  360.     struct gfx_object_list *object_list;
  361.  
  362.     for(object_list=first_object_list ; object_list != 0 ; object_list=object_list->next)
  363.         gfxobj_update_one(object_list);
  364. }
  365.  
  366. static void draw_object_one(struct osd_bitmap *bitmap,struct gfx_object *object)
  367. {
  368.     if(object->special_handler)
  369.     {    /* special object , callback user draw handler */
  370.         object->special_handler(bitmap,object);
  371.     }
  372.     else
  373.     {    /* normaly gfx object */
  374.         drawgfx(bitmap,object->gfx,
  375.                 object->code,
  376.                 object->color,
  377.                 object->flipx,
  378.                 object->flipy,
  379.                 object->draw_x,
  380.                 object->draw_y,
  381.                 &object->clip,
  382.                 object->transparency,
  383.                 object->transparet_color);
  384.     }
  385. }
  386.  
  387. void gfxobj_draw(struct gfx_object_list *object_list)
  388. {
  389.     struct osd_bitmap *bitmap = Machine->scrbitmap;
  390.     struct gfx_object *object;
  391.  
  392.     for(object=object_list->first_object ; object ; object=object->next)
  393.     {
  394.         if(object->visible )
  395.             draw_object_one(bitmap,object);
  396.     }
  397. }
  398.